/*
 * @Author: dgflash
 * @Date: 2022-06-28 17:57:23
 * @LastEditors: dgflash
 * @LastEditTime: 2022-09-20 10:29:15
 */

import chalk from "chalk";
import { HttpClient, HttpServer, HttpServerOptions, PrefixLogger, WsClient, WsServer, WsServerOptions } from "tsrpc";

import { serviceProto as GateServiceProto, ServiceType as GateServiceType } from "../../tsrpc/shared/protocols/GateServiceProto";
import { serviceProto as AccountServiceProto, ServiceType as AccountServiceType } from "../../tsrpc/shared/protocols/AccountServiceProto";
import { serviceProto as HallServiceProto, ServiceType as HallServiceType } from "../../tsrpc/shared/protocols/HallServiceProto";

import { Config } from "../config/Config";
import { CommonUtil } from "./CommonUtil";
import { ShareConfig } from "../config/ShareConfig";
import { Security } from "./Security";
import { BaseConf, BaseRequest } from "../../tsrpc/shared/protocols/base";

/** TSRPC 客户端、服务器对象工厂 */
export class CommonFactory {
    /** 创建 Http 网关服务端对象 */
    static createHsGate() {
        var options: Partial<HttpServerOptions<GateServiceType>> = {
            port: parseInt(Config.gate.port),
            json: ShareConfig.json,
            https: CommonUtil.getCertificate()
        }

        var hs = new HttpServer(GateServiceProto, options);
        this.flowServerApi(hs);

        return hs;
    }

    /** 创建 Http 账号服务端对象 */
    // static createHsAccount() {
    //     var options: Partial<HttpServerOptions<AccountServiceType>> = {
    //         port: parseInt(Config.match.port),
    //         json: ShareConfig.json,
    //         https: CommonUtil.getCertificate()
    //     }

    //     var hs = new HttpServer(AccountServiceProto, options);
    //     this.flowServerApi(hs);
    //     //account.checkAuth(hs);                     // 检查客户端身份

    //     return hs;
    // }

    /** 创建 Websocket 房间服务器 */
    static createWssRoom() {
        let options: Partial<WsServerOptions<GateServiceType>> = {
            port: parseInt(Config.room.port),
            logMsg: Config.room.logMsg,
            json: ShareConfig.json,
            wss: CommonUtil.getCertificate()
        }

        let wss = new WsServer(GateServiceProto, options);
        this.flowServerMsg(wss);
        this.checkAuth(wss);                   // 检查客户端身份

        return wss;
    }

    static checkAuth(server: HttpServer | WsServer) {
        server.flows.preApiCallFlow.push(async (call) => {
            let conf: BaseConf | undefined = call.service.conf;
            //let req = call.return as BaseRequest;
            // 执行 API 接口实现之前通过令牌获取当前用户信息
            //let req = call.req as BaseRequest;
            // if (req.__ssoToken) {
            //     const user = this.parseSSO(req.__ssoToken);
            //     if (user != null) {
            //         call.user = user
            //     }
                
            // }

            // 验证请求客户端地址是否在白名单列表中
            if (conf?.needCheckAddress && (Config.ips as any)[call.conn.ip] == undefined) {
                await call.error('没有访问权限', { code: 'NEED_AUTHORITY' });
                return null;
            }
            // // 玩家必须登录才可以访问服务
            // else if (conf?.needLogin && !call.user) {
            //     await call.error('登录后获取访问权限', { code: 'NEED_LOGIN' });
            //     return null;
            // }

            return call;
        });
    }

    // /**
    //  * 创建 Websocket 匹配服务连接房间服务器的客户端
    //  * @param serverUrl     房间 Websocket 服务器地址
    //  * @param server        匹配服务器对象
    //  * @returns WsClient
    //  */
    // static createWscRoom(serverUrl: string, server: HttpServer) {
    //     let wsc = new WsClient(ServiceProtoRoom, {
    //         server: serverUrl,
    //         logger: new PrefixLogger({
    //             logger: server.logger,
    //             prefixs: [chalk.green(`房间服务器 ${serverUrl}`)]
    //         }),
    //         heartbeat: {
    //             interval: ShareConfig.heartbeat_interval,
    //             timeout: ShareConfig.heartbeat_timeout
    //         },
    //         logMsg: Config.room.logMsg
    //     });
    //     this.flowClientMsg(wsc);

    //     return wsc;
    // }

    /** 创建匹配服务器的 Http 客户端连接 */
    static createHcAccount() {
        let url = `${ShareConfig.https ? "https" : "http"}://${Config.account.ip}:${Config.account.port}/`;
        let hc = new HttpClient(AccountServiceProto, { server: url });
        this.flowClientApi(hc);

        return hc;
    }

    /** 创建匹配服务器的 Http 客户端连接 */
    static createHcHall() {
        let url = `${ShareConfig.https ? "https" : "http"}://${Config.account.ip}:${Config.account.port}/`;
        let hc = new HttpClient(HallServiceProto, { server: url });
        this.flowClientApi(hc);

        return hc;
    }

    // /** HTTP 服务端协议数据加密、解密 */
    private static flowServerApi(hs: HttpServer) {
        if (!ShareConfig.security) return;

        // 在将数据发送到网络之前，通常要进行加密/解密
        hs.flows.preSendDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.encrypt(v.data);
            }
            return v;
        });

        // 在处理接收到的数据之前，通常要进行加密/解密
        hs.flows.preRecvDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.decrypt(v.data);
            }
            return v;
        });
    }

    // // /** HTTP 客户端协议数据加密、解密 */
    private static flowClientApi(hc: HttpClient<AccountServiceType>| HttpClient<GateServiceType>|HttpClient<HallServiceType>) {
        if (!ShareConfig.security) return;

        hc.flows.preSendDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.encrypt(v.data);
            }
            return v;
        });

        // 在处理接收到的数据之前，通常要进行加密/解密
        hc.flows.preRecvDataFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.decrypt(v.data);
            }
            return v;
        });

    }

    // /** WebSocket 服务器协议数据加密、解密 */
    private static flowServerMsg(wss: WsServer) {
        if (!ShareConfig.security) return;

        wss.flows.preSendMsgFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.encrypt(v.data);
            }
            return v;
        });

        // 在处理 MsgCall 之前
        wss.flows.preMsgCallFlow.push((v: any) => {
            if (v.data instanceof Uint8Array) {
                v.data = Security.decrypt(v.data);
            }
            return v;
        });
    }

    // /** WebSocket 客户端协议数据加密、解密 */
    // private static flowClientMsg(wsc: WsClient<ServiceTypeRoom>) {
    //     if (!ShareConfig.security) return;

    //     // 发送 Message 之前
    //     wsc.flows.preSendMsgFlow.push((v: any) => {
    //         if (v.data instanceof Uint8Array) {
    //             v.data = Security.encrypt(v.data);
    //         }
    //         return v;
    //     });

    //     // 触发 Message 监听事件之前
    //     wsc.flows.preRecvMsgFlow.push((v: any) => {
    //         if (v.data instanceof Uint8Array) {
    //             v.data = Security.decrypt(v.data);
    //         }
    //         return v;
    //     });
    // }
}